package org.example.forkjoin;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * @author zhengdp
 * @Description Fork Join 使用方法案例
 * @Date 2022/12/25 23:04
 * @Created by zhengdp
 */
@Slf4j(topic = "c.TestForkJoin")
public class TestForkJoin {
    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(4);
        System.out.println(pool.invoke(new AddTask(1,5)));
    }
}

@Slf4j(topic = "c.AddTask")
class AddTask extends RecursiveTask<Integer> {
    // 1   用于i表示区间
    int begin;
    // n
    int end;

    public AddTask(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    public String toString(){
        return "{" + begin + " , " + end + "}";
    }

    /**
     * 分治 （归并排序)
     * @return
     */
    @Override
    protected Integer compute() {
        if(begin == end) {
            log.info("join () {} ",begin);
            return begin;
        }
        if(end - begin == 1) {
            log.info("join() {} + {} = {}",begin,end,begin + end);
            return end + begin;
        }

        int mid = (end + begin ) /2;

        AddTask t1 = new AddTask(begin,mid);
        t1.fork();
        AddTask t2 = new AddTask(mid + 1,end);
        t2.fork();
        log.info("fork() {} + {} = ?",t1,t2);
        int result = t1.join() + t2.join();
        log.info("join () {} + {} = {} ",t1,t2,result);
        return result;
    }
}

/**
 * 求 1 ~ n 之间整数的和
 */
@Slf4j(topic = "c.MyTask")
class MyTask extends RecursiveTask<Integer> {
    private int n ;

    public MyTask(int n ) {
        this.n = n;
    }

    @Override
    public String toString(){
        return "{" + n + "}";
    }

    /**
     * 进行任务的拆分操作 (在该方法中写递归）
     * result = N + MyTask(N-1)
     * @return
     */
    @Override
    protected Integer compute() {
        if( n == 1){
            log.info("join() {}" , n);
            return 1;
        }
        MyTask t1 = new MyTask(n-1);
        // 让线程去执行该任务
        t1.fork();
        log.info("fork() {} + {}",n ,t1);
        // 获取任务结果
        int result = n + t1.join();
        log.info("join() {} + {} = {}",n , t1,result);
        return result;
    }
}
